package com.corn.security;

import cn.hutool.core.map.MapUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author : Jim Wu
 * @version 1.0
 * @function :
 * @since : 2021/4/12 10:35
 */

public class RedisTokenRepository implements PersistentTokenRepository {
    private final RedisTemplate<String, Object> redisTemplate;

    private final String SECURITY_TOKEN_PREFIX = "SECURITY_TOKEN:";

    private final String SECURITY_USERNAME_SERIAL_PREFIX = "SECURITY_USERNAME_TOKEN:";

    public RedisTokenRepository(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 生成新的token 保存到redis中 使用hash保存 token username date 3个字段
     * 因为removeToken使用的是username来删除 所以需要 将username 和 serialId的关系也保存下来
     *
     * @param token
     */
    @Override
    public void createNewToken(PersistentRememberMeToken token) {
        redisTemplate.opsForHash().put(SECURITY_TOKEN_PREFIX + token.getSeries(), "token", token.getTokenValue());
        redisTemplate.opsForHash().put(SECURITY_TOKEN_PREFIX + token.getSeries(), "username", token.getUsername());
        redisTemplate.opsForHash().put(SECURITY_TOKEN_PREFIX + token.getSeries(), "date", token.getDate());
        redisTemplate.expire(SECURITY_TOKEN_PREFIX + token.getSeries(), 1, TimeUnit.HOURS);
        redisTemplate.opsForValue().set(SECURITY_USERNAME_SERIAL_PREFIX + token.getUsername(), token.getSeries());
    }

    /**
     * 更新token
     *
     * @param series
     * @param tokenValue
     * @param lastUsed
     */
    @Override
    public void updateToken(String series, String tokenValue, Date lastUsed) {
        if (redisTemplate.hasKey(SECURITY_TOKEN_PREFIX + series)) {
            redisTemplate.opsForHash().put(SECURITY_TOKEN_PREFIX + series, "token", tokenValue);
            redisTemplate.expire(SECURITY_TOKEN_PREFIX + series, 1, TimeUnit.HOURS);
        }
    }

    /**
     * 通过seriesId 来查询token
     *
     * @param seriesId
     * @return
     */
    @Override
    public PersistentRememberMeToken getTokenForSeries(String seriesId) {
        String redisKey = SECURITY_TOKEN_PREFIX + seriesId;
        Map<Object, Object> objectMap = redisTemplate.opsForHash().entries(redisKey);
        if (MapUtil.isNotEmpty(objectMap)) {
            return new PersistentRememberMeToken((String) objectMap.get("username"), seriesId, (String) objectMap.get("token"), new Date(System.currentTimeMillis() + redisTemplate.getExpire(redisKey, TimeUnit.MILLISECONDS)));
        }
        return null;
    }

    /**
     * 删除一个token
     *
     * @param username
     */
    @Override
    public void removeUserTokens(String username) {
        String seriesId = (String) redisTemplate.opsForValue().get(SECURITY_USERNAME_SERIAL_PREFIX + username);
        if (!StringUtils.isEmpty(seriesId) && redisTemplate.hasKey(SECURITY_TOKEN_PREFIX + seriesId)) {
            redisTemplate.delete(SECURITY_TOKEN_PREFIX + seriesId);
        }
    }
}
